﻿#pragma once
#include "yzrutil.h"
#include "Token.h"
#include "collection/ArrayList.hpp"
#include "lang/String.h"

namespace yzrilyzr_ast{
	EBCLASS(TokenReader){
	public:
	yzrilyzr_collection::ArrayList<std::string> imports;
	yzrilyzr_collection::ArrayList<Token *> tokens;
	u_index index=0;
	void add(CharReader & charReader, TokenType type, char c){
		tokens.add(new Token(charReader, std::to_string(c), type));
	}
	void add(CharReader & charReader, TokenType type, const std::string & c){
		tokens.add(new Token(charReader, c, type));
	}
	yzrilyzr_lang::String toString()const override{
		/*if(tokens.size()>30000){
			return std::string.format("[Too long,Current is:%s",getString());
		}
		String sb=new String();
		for(u_index i=0;i<tokens.size();i++){
			Token token=tokens.get(i);
			if(i==index) sb.append("[POS->");
			sb.append(token.token).append(" ");
		}
		if(!tokens.isEmpty()) sb.deleteCharAt(sb.length()-1);
		return sb.toString();*/
		return "unimpl";
	}
	std::string getString(){
		return getString(0);
	}
	bool getSign(){
		if(index < 1)return true;
		Token & t=getToken(-1);
		if(t.type == TokenType::Symbol && t.token == "-")return false;
		return true;
	}
	float getFloat(){
		return std::stof(getString(0).c_str()) * (getSign()?1.0f:-1.0f);
	}
	double getDouble(){
		return std::stod(getString(0).c_str()) * (getSign()?1.0:-1.0);
	}
	int32_t getInt(){
		return std::stol(getString(0).c_str()) * (getSign()?1:-1);
	}
	int64_t getLong(){
		return std::stoll(getString(0).c_str()) * (getSign()?1:-1);
	}
	bool getBoolean(){
		return getString(0) == "true"?true:false;
	}
	std::string getString(u_index offset){
		return getToken(offset).token;
	}
	Token & getToken(u_index offset){
		return *tokens.get(index + offset);
	}
	void skipTo(const std::string & s){
		while(until(s)){
			next();
		}
	}
	bool until(const std::string & s){
		if(has()){
			if(s == getString()) return false;
			return true;
		}
		return false;
	}
	/*bool until(String* s){
		if(has()){
			for(String a:s){
				if(a.equals(getString())) return false;
			}
			return true;
		}
		return false;
	}*/
	void next(){
		index+=1;
	}
	bool has(){
		return index < tokens.size();
	}
	void prev(){
		index-=1;
	}
	void skipTo(TokenType type){
		while(until(type)){
			next();
		}
	}
	bool until(TokenType type){
		return has() && getToken().type != type;
	}
	Token & getToken(){
		return getToken(0);
	}
	u_index size(){
		return tokens.size();
	}
	bool isNot(const char * endOf){
		u_index l=getString().length();
		if(l != 1) return true;
		char not1=getChar();
		u_index len=strlen(endOf);
		for(u_index i=0;i < len;i++){
			if(endOf[i] == not1) return false;
		}
		return true;
	}
	char getChar(){
		return getChar(0);
	}
	char getChar(int offset){
		Token & s=getToken(offset);
		if(s.token.length() > 1) throw yzrilyzr_lang::Exception(yzrilyzr_lang::String("Unexpected token length:") + s);
		return yzrilyzr_lang::String(s.token)[0];
	}
	};
}